package com.huishu.tcm.controller;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huishu.tcm.entity.User;
import com.huishu.tcm.service.UserService;
import com.huishu.tcm.task.VerificationCodeService;
import com.huishu.tcm.util.AESUtil;
import com.huishu.tcm.util.Constants;
import com.huishu.tcm.util.SmsUtil;
import com.huishu.tcm.util.exception.TcmException;
import com.huishu.tcm.util.exception.TcmExceptionEnum;
import com.huishu.tcm.vo.SmsResponseVo;
import com.huishu.tcm.vo.VerificationCodeVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import java.util.Date;
import java.util.List;

@Api(tags = "权限认证")
@RestController
@RequestMapping("/api/auth")
@Slf4j
public class AuthController {

    @Resource
    UserService userService;

    // 获取验证码
    @ApiOperation(value = "获取验证码", notes = "获取验证码")
    @GetMapping(value = "/getVerificationCode", params = {"telNum"})
    public void getVerificationCode(String telNum) throws Exception{
        String verificationCode = String.valueOf(Math.round(Math.random() * 10000));
        Date expirationDate = new Date(new Date().getTime() + 5 * 60 * 1000);
        try{
            SmsResponseVo responseVo = SmsUtil.sendSms(telNum,verificationCode);
            log.info( "发送验证码返回值：" + JSONObject.toJSONString(responseVo));
        }catch (Exception e){
            throw new TcmException(TcmExceptionEnum.SMS_SEND_ERROR);
        }
        // 删除该手机号已发送的验证码
        VerificationCodeService.removeVerificationCode(telNum);
        // 保存当前验证码
        VerificationCodeVo v = new VerificationCodeVo();
        v.setTelNum(telNum);
        v.setExpirationDate(expirationDate);
        v.setVerificationCode(verificationCode);
        VerificationCodeService.addVerificationCode(v);
    }

    @ApiOperation(value = "使用手机号验证码修改密码", notes = "使用手机号验证码修改密码")
    @GetMapping(value = "/changePwdByVerificationCode", params = {"telNum","verificationCode","password"})
    public void changePwdByVerificationCode( String telNum,  String verificationCode,  String password) throws Exception {
        // 判断验证码是否正确、是否过期
        List<VerificationCodeVo> verificationCodeVoList = VerificationCodeService.verificationCodeVoList;
        VerificationCodeVo verificationCodeVo = null;
        Date now = new Date();
        for(VerificationCodeVo v : verificationCodeVoList){
            if(v.getTelNum().equals(telNum) && v.getVerificationCode().equals(verificationCode)
                && now.before(v.getExpirationDate())){
                verificationCodeVo = v;
                break;
            }
        }
        if(verificationCodeVo == null){
            throw new TcmException(TcmExceptionEnum.USER_WRONG_VERIFICATION_CODE);
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.eq("tel_num", telNum);
        User user = userService.getOne(queryWrapper);
        if(ObjectUtil.isEmpty(user)){
            throw new TcmException(TcmExceptionEnum.USER_ACCOUNT_NOT_EXIST);
        }
        String pwd = AESUtil.encrypt(password,AESUtil.key);
        user.setPassword(pwd);
        userService.update(user, queryWrapper);
    }

    @ApiOperation(value = "注册", notes = "医生和患者的注册接口 ，字段role值为patient、doctor")
    @PostMapping("/register")
    public void register( @RequestBody User user) throws Exception {
        // 判断验证码是否正确
        List<VerificationCodeVo> verificationCodeVoList = VerificationCodeService.verificationCodeVoList;
        VerificationCodeVo verificationCodeVo = null;
        Date now = new Date();
        for(VerificationCodeVo v: verificationCodeVoList){
            if(v.getTelNum().equals(user.getTelNum()) && v.getVerificationCode().equals(user.getVerificationCode())
                && now.before(v.getExpirationDate())){
                verificationCodeVo = v;
                break;
            }
        }
        if(verificationCodeVo == null){
            throw new TcmException(TcmExceptionEnum.USER_WRONG_VERIFICATION_CODE);
        }
        // 判断手机号是否已注册
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tel_num", user.getTelNum());
        List<User> userList = userService.list(queryWrapper);
        if(userList.size() > 0 && userList.get(0).getRegisterStatus().equals(Constants.USER_REGISTER_STATUS_success)){
            throw new TcmException(TcmExceptionEnum.DATA_ALREADY_EXISTS.getCode(), "该手机号已注册");
        }
        // 保存用户信息
        if(Constants.USER_ROLE_DOCTOR.equals(user.getRole())){ // 医生
            // 如果是因为审核不通过重新注册的
            if(userList.size() > 0){
                user = userList.get(0);
                user.setPassword(AESUtil.encrypt(user.getPassword(),AESUtil.key));
                user.setRegisterStatus(Constants.USER_REGISTER_STATUS_ToBeReviewed);
                user.setUpdateTime(now);
                userService.updateById(user);
            }else{
                user.setPassword(AESUtil.encrypt(user.getPassword(),AESUtil.key));
                user.setRegisterStatus(Constants.USER_REGISTER_STATUS_ToBeReviewed);
                user.setCreateTime(now);
                user.setUpdateTime(now);
                userService.save(user);
            }
        }else if(Constants.USER_ROLE_PATIENT.equals(user.getRole())){ // 患者
            user.setEndManagement(false);
            user.setRegisterStatus(Constants.USER_REGISTER_STATUS_success);
            user.setCreateTime(now);
            user.setUpdateTime(now);
            userService.save(user);
        }else{
            throw new TcmException(TcmExceptionEnum.DATA_FIELD_VALUE_IS_INCORRECT.getCode(), "用户角色错误，请确认");
        }
    }

    @ApiOperation(value = "使用验证码登录", notes = "使用验证码登录")
    @PostMapping(value = "/loginWithVerificationCode", params = {"telNum", "verificationCode"})
    public SaTokenInfo loginWithVerificationCode(String telNum, String verificationCode) throws TcmException{
        List<VerificationCodeVo> verificationCodeVoList = VerificationCodeService.verificationCodeVoList;
        Date now = new Date();
        for(VerificationCodeVo v : verificationCodeVoList){
            // 1、判断手机号是否相同 2、判断验证码是否相同 3、判断验证码是否过期
            if(v.getTelNum().equals(telNum) && v.getVerificationCode().equals(verificationCode)
                && now.before(v.getExpirationDate())){
                QueryWrapper<User> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("tel_num",telNum);
                User user = userService.getOne(queryWrapper);
                if(!Constants.USER_REGISTER_STATUS_success.equals(user.getRegisterStatus())){
                    throw new TcmException(TcmExceptionEnum.USER_ACCOUNT_NOT_EXIST.getCode(),"用户暂未审核或审核失败，请联系管理员。");
                }
                if(ObjectUtil.isNotEmpty(user)){
                    StpUtil.login(JSONObject.toJSONString(user));
                    return StpUtil.getTokenInfo();
                }else{
                    throw new TcmException(TcmExceptionEnum.USER_ACCOUNT_NOT_EXIST);
                }
            }
        }
        throw new TcmException(TcmExceptionEnum.USER_WRONG_VERIFICATION_CODE);
    }

    @ApiOperation(value = "使用密码登录", notes = "使用密码登录")
    @PostMapping("/login")
    public SaTokenInfo login(@RequestBody User user) throws Exception {
        if(ObjectUtil.isEmpty(user)){
            throw new TcmException(TcmExceptionEnum.USER_WRONG_ACCOUNT_PASSWORD);
        }
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("tel_num",user.getTelNum());
        User u = userService.getOne(wrapper);
        if(!Constants.USER_REGISTER_STATUS_success.equals(u.getRegisterStatus())){
            throw new TcmException(TcmExceptionEnum.USER_ACCOUNT_NOT_EXIST.getCode(),"用户暂未审核或审核失败，请联系管理员。");
        }
        if(ObjectUtil.isNotEmpty(u)){
            String pwd = AESUtil.encrypt(user.getPassword(),AESUtil.key);
            if(u.getPassword().equals(pwd)){
                StpUtil.login(JSONObject.toJSONString(u));
                return StpUtil.getTokenInfo();
            }
        }
        throw new TcmException(TcmExceptionEnum.USER_WRONG_ACCOUNT_PASSWORD);
    }

    @ApiOperation(value = "退出登录", notes = "退出登录")
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public void logout(){
        StpUtil.logout();
    }
    @ApiOperation(value = "判断是否登录", notes = "判断是否登录")
    @RequestMapping(value = "/isLogin", method = RequestMethod.GET)
    public boolean isLogin() {
        return StpUtil.isLogin();
    }

}
